// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   FieldParseInfo.java

package com.solab.iso8583.parse;

import com.solab.iso8583.IsoType;
import com.solab.iso8583.IsoValue;
import com.solab.iso8583.common.ByteUtil;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;

public class FieldParseInfo
{

	private IsoType type;
	private int length;

	public FieldParseInfo(IsoType t, int len)
	{
		if (t == null)
		{
			throw new IllegalArgumentException("IsoType cannot be null");
		} else
		{
			type = t;
			length = len;
			return;
		}
	}

	public int getLength()
	{
		return length;
	}

	public IsoType getType()
	{
		return type;
	}

	public IsoValue parse(byte buf[], int pos)
		throws ParseException
	{
		if (type == IsoType.NUMERIC || type == IsoType.ALPHA)
			return new IsoValue(type, new String(buf, pos, length), length);
		if (type == IsoType.LLVAR)
		{
			length = (buf[pos] - 48) * 10 + (buf[pos + 1] - 48);
			return new IsoValue(type, new String(buf, pos + 2, length));
		}
		if (type == IsoType.LLLVAR)
		{
			length = (buf[pos] - 48) * 100 + (buf[pos + 1] - 48) * 10 + (buf[pos + 2] - 48);
			return new IsoValue(type, new String(buf, pos + 3, length));
		}
		if (type == IsoType.LLLVARCN)
		{
			length = (buf[pos] - 48) * 100 + (buf[pos + 1] - 48) * 10 + (buf[pos + 2] - 48);
			return new IsoValue(type, (new StringBuilder(String.valueOf(new String(buf, pos, 3)))).append(ByteUtil.bytesToHexString(ByteUtil.getsubByte(buf, pos + 3, length))).toString(), length);
		}
		if (type == IsoType.AMOUNT)
		{
			byte c[] = new byte[13];
			System.arraycopy(buf, pos, c, 0, 10);
			System.arraycopy(buf, pos + 10, c, 11, 2);
			c[10] = 46;
			return new IsoValue(type, new BigDecimal(new String(c)));
		}
		if (type == IsoType.DATE10)
		{
			Calendar cal = Calendar.getInstance();
			cal.set(2, ((buf[pos] - 48) * 10 + buf[pos + 1]) - 49);
			cal.set(5, ((buf[pos + 2] - 48) * 10 + buf[pos + 3]) - 48);
			cal.set(11, ((buf[pos + 4] - 48) * 10 + buf[pos + 5]) - 48);
			cal.set(12, ((buf[pos + 6] - 48) * 10 + buf[pos + 7]) - 48);
			cal.set(13, ((buf[pos + 8] - 48) * 10 + buf[pos + 9]) - 48);
			if (cal.getTime().after(new Date()))
				cal.add(1, -1);
			return new IsoValue(type, cal.getTime());
		}
		if (type == IsoType.DATE4)
		{
			Calendar cal = Calendar.getInstance();
			cal.set(10, 0);
			cal.set(12, 0);
			cal.set(13, 0);
			cal.set(2, ((buf[pos] - 48) * 10 + buf[pos + 1]) - 49);
			cal.set(5, ((buf[pos + 2] - 48) * 10 + buf[pos + 3]) - 48);
			if (cal.getTime().after(new Date()))
				cal.add(1, -1);
			return new IsoValue(type, cal.getTime());
		}
		if (type == IsoType.DATE_EXP)
		{
			Calendar cal = Calendar.getInstance();
			cal.set(10, 0);
			cal.set(12, 0);
			cal.set(13, 0);
			cal.set(5, 1);
			cal.set(1, ((cal.get(1) - cal.get(1) % 100) + (buf[pos] - 48) * 10 + buf[pos + 1]) - 48);
			cal.set(2, ((buf[pos + 2] - 48) * 10 + buf[pos + 3]) - 49);
			return new IsoValue(type, cal.getTime());
		}
		if (type == IsoType.TIME)
			return new IsoValue(type, new String(buf, pos, 6));
		if (type == IsoType.DATE14)
			return new IsoValue(type, new String(buf, pos, 14));
		if (type == IsoType.DATE8)
			return new IsoValue(type, new String(buf, pos, 8));
		else
			return null;
	}

	public IsoValue parseBinary(byte buf[], int pos)
		throws ParseException
	{
		if (type == IsoType.ALPHA)
			return new IsoValue(type, new String(buf, pos, length), length);
		if (type == IsoType.NUMERIC)
		{
			if (length < 19)
			{
				long l = 0L;
				int power = 1;
				for (int i = (pos + length / 2 + length % 2) - 1; i >= pos; i--)
				{
					l += (buf[i] & 0xf) * power;
					power *= 10;
					l += ((buf[i] & 0xf0) >> 4) * power;
					power *= 10;
				}

				return new IsoValue(IsoType.NUMERIC, new Long(l), length);
			}
			char digits[] = new char[length];
			int start = 0;
			for (int i = pos; i < pos + length / 2 + length % 2; i++)
			{
				digits[start++] = (char)(((buf[i] & 0xf0) >> 4) + 48);
				digits[start++] = (char)((buf[i] & 0xf) + 48);
			}

			return new IsoValue(IsoType.NUMERIC, new BigInteger(new String(digits)), length);
		}
		if (type == IsoType.LLVAR)
		{
			length = ((buf[pos] & 0xf0) >> 4) * 10 + (buf[pos] & 0xf);
			return new IsoValue(type, new String(buf, pos + 1, length));
		}
		if (type == IsoType.LLLVAR)
		{
			length = (buf[pos] & 0xf) * 100 + ((buf[pos + 1] & 0xf0) >> 4) * 10 + (buf[pos + 1] & 0xf);
			return new IsoValue(type, new String(buf, pos + 2, length));
		}
		if (type == IsoType.AMOUNT)
		{
			char digits[] = new char[13];
			digits[10] = '.';
			int start = 0;
			for (int i = pos; i < pos + 6; i++)
			{
				digits[start++] = (char)(((buf[i] & 0xf0) >> 4) + 48);
				digits[start++] = (char)((buf[i] & 0xf) + 48);
				if (start == 10)
					start++;
			}

			return new IsoValue(IsoType.AMOUNT, new BigDecimal(new String(digits)));
		}
		if (type == IsoType.DATE10 || type == IsoType.DATE4 || type == IsoType.DATE_EXP || type == IsoType.TIME)
		{
			int tens[] = new int[type.getLength() / 2 + type.getLength() % 2];
			int start = 0;
			for (int i = pos; i < pos + tens.length; i++)
				tens[start++] = ((buf[i] & 0xf0) >> 4) * 10 + (buf[i] & 0xf);

			Calendar cal = Calendar.getInstance();
			if (type == IsoType.DATE10)
			{
				cal.set(2, tens[0] - 1);
				cal.set(5, tens[1]);
				cal.set(11, tens[2]);
				cal.set(12, tens[3]);
				cal.set(13, tens[4]);
				if (cal.getTime().after(new Date()))
					cal.add(1, -1);
				return new IsoValue(type, cal.getTime());
			}
			if (type == IsoType.DATE4)
			{
				cal.set(10, 0);
				cal.set(12, 0);
				cal.set(13, 0);
				cal.set(2, tens[0] - 1);
				cal.set(5, tens[1]);
				if (cal.getTime().after(new Date()))
					cal.add(1, -1);
				return new IsoValue(type, cal.getTime());
			}
			if (type == IsoType.DATE_EXP)
			{
				cal.set(10, 0);
				cal.set(12, 0);
				cal.set(13, 0);
				cal.set(5, 1);
				cal.set(1, (cal.get(1) - cal.get(1) % 100) + tens[0]);
				cal.set(2, tens[1] - 1);
				return new IsoValue(type, cal.getTime());
			}
			if (type == IsoType.TIME)
			{
				cal.set(11, tens[0]);
				cal.set(12, tens[1]);
				cal.set(13, tens[2]);
				return new IsoValue(type, cal.getTime());
			} else
			{
				return new IsoValue(type, cal.getTime());
			}
		} else
		{
			return null;
		}
	}
}
